package com.hotec.PROJECT_NAME.component.basic;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.hotec.PROJECT_NAME.component.exception.exc.BizException;
import com.hotec.PROJECT_NAME.utils.UtilAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 运行时字典项，使用参考 framework_example中的 com.framework.demo.model.entity.support.DemoType 对象
 * @Author : liupeng
 * @Date : 2018/7/25 17:11
 * @Modified By
 */
@Slf4j
@RestController
@RequestMapping( value = {"/api"+ AppDictionaryRuntimeController.BASE_PATH } )
public class AppDictionaryRuntimeController extends BaseController {

    public static final String BASE_PATH  = "/dictionary/runtime" ;

    // 扫描 HotecEnum 的基础包
    private static Set<String> dictRuntimeClassPackages = Sets.newHashSet() ;

    private static Map<String,Class<? extends HotecEnum>> runtimeDictMap = Maps.newHashMap() ;

    /**
     * 添加运行时字典项的基类
     * @param dictRuntimeClassPackage
     */
    public static void addDictRuntimeClassPackage(String dictRuntimeClassPackage){
        if( dictRuntimeClassPackages.contains( dictRuntimeClassPackage ) ){
            return ;
        }
        Reflections reflections = new Reflections( dictRuntimeClassPackage ) ;

        Set<Class<? extends HotecEnum>> appRuntimeDictClasses = reflections.getSubTypesOf( HotecEnum.class ) ;

        for (Class<? extends HotecEnum> appRuntimeDictClass : appRuntimeDictClasses) {
            AppDict appDict = UtilAnnotation.findAnnotation( appRuntimeDictClass , AppDict.class ) ;

            if(ObjectUtil.isNull(appDict)) continue;

            String dictParentCode = appDict.value() ;

            if(StrUtil.isBlank( dictParentCode )){
                log.info("运行时字典 {} 的rest地址访问为空" , appRuntimeDictClass.getName());
                continue;
            }

            log.info("运行时字典 {} 的rest地址访问地址: {}" , appRuntimeDictClass.getName() , BASE_PATH + "/" +appDict.value() ) ;

            Assert.isTrue( !runtimeDictMap.containsKey( dictParentCode ) , "运行时字典 "+dictParentCode+" 已经存在");

            runtimeDictMap.put( dictParentCode , appRuntimeDictClass ) ;
        }
    }

    public AppDictionaryRuntimeController(){
        String [] packages={"com.hotec"};
        // 添加运行时字典映射
        for (String basePackage : packages) {
            addDictRuntimeClassPackage( basePackage ) ;
        }
    }

    @GetMapping("{code}")
    public Object runtimeDictionary(@PathVariable String code ,
                                           @RequestParam(required = false) String excludes ,
                                           @RequestParam(required = false , defaultValue = "true") Boolean wrapped){
        if( !runtimeDictMap.containsKey( code ) ){
            throw new BizException("没有指定的字典项");
        }

        Class<?> runtimeDictClass = runtimeDictMap.get( code ) ;

        if( !runtimeDictClass.isEnum() ){
            throw new BizException("运行时字典必须为枚举类型");
        }

        HotecEnum[] hotecEnums = null ;

        // 通过反射机制获取所有的枚举类型
        try {
            Method valuesMethod = runtimeDictClass.getMethod("values") ;
            hotecEnums = (HotecEnum[])valuesMethod.invoke( null , null ) ;
        } catch (Exception e) {
            throw new BizException("运行时字典必须为枚举类型");
        }



        // 构造字典列表
        if( hotecEnums != null ){
            // 获取排除的编码
            List<String> excludeCodes = StrUtil.splitTrim( excludes, "," ) ;
            List<Map<String,String>> dictList = Lists.newArrayListWithExpectedSize(hotecEnums.length ) ;
            Arrays.stream(hotecEnums)
                    .filter( appRuntimeDict -> !excludeCodes.contains( appRuntimeDict.name() ) )
                    .forEach( appRuntimeDict -> {
              Map<String,String> item = Maps.newHashMapWithExpectedSize(2) ;
              item.put("code" , appRuntimeDict.name() ) ;
              item.put("name" , appRuntimeDict.getRemark() ) ;
              dictList.add( item ) ;
            }) ;

            // 如果不需要进一步封装结构，直接返回list
            if( !wrapped ){
                return dictList ;
            }

           return this.success().setData( dictList ) ;
        }

        return this.success() ;
    }

//    public static void main(String[] args) throws Exception {
//
//        // 获取字段类型
//        Field field = GWGroup.class.getDeclaredField( "status") ;
//        Class<?> fieldClass = field.getType() ;
//
//        try {
//            Object value = Enum.valueOf( (Class< ? extends Enum>) fieldClass , "ONLINE" ) ;
//
////            Method valueOfMethod = fieldClass.getDeclaredMethod("valueOf") ;
////            Object value = valueOfMethod.invoke( null , "ONLINE" ) ;
//
//            System.out.println(value);
//        }catch (Exception e){
//            e.printStackTrace() ;
//        }
//    }

}
